#include "ASMInstruction.hpp"
#include "CodeGen.hpp"
#include "Module.hpp"

#include <iostream>
#include <memory>
#include <unordered_map>

// 主函数声明：将高级语言翻译为目标架构汇编
void translate_main(CodeGen *codegen);

int main() {
    // 初始化编译器模块和代码生成器
    auto *module = new Module();
    auto *codegen = new CodeGen(module);

    // 指定后续生成的汇编代码属于.text段（代码段）
    codegen->append_inst(".text", ASMInstruction::Atrribute);

    // 执行实际的代码翻译工作
    translate_main(codegen);

    // 输出生成的汇编代码
    std::cout << codegen->print();
    
    // 清理资源
    delete codegen;
    delete module;
    return 0;
}

// RISC-V浮点比较和条件分支实现
void translate_main(CodeGen *codegen) {
    // 符号表：记录变量在栈帧中的偏移位置
    std::unordered_map<std::string, int> offset_map;

    /* ============== 函数声明部分 ============== */
    codegen->append_inst(".globl main", ASMInstruction::Atrribute);  // 全局可见符号
    codegen->append_inst(".type main, @function", ASMInstruction::Atrribute); // 函数类型标识

    /* ============== 函数入口点 ============== */
    codegen->append_inst("main", ASMInstruction::Label);  // 函数入口标签

    /* ============== 序言部分 (Prologue) ============== */
    // 分配32字节栈空间（包含保存寄存器和局部变量的空间）
    codegen->append_inst("addi sp, sp, -32");
    // 保存返回地址寄存器(ra)到栈中
    codegen->append_inst("sd ra, 24(sp)");
    // 保存旧的帧指针(s0)
    codegen->append_inst("sd s0, 16(sp)");
    // 设置新的帧指针(s0 = sp + 32)
    codegen->append_inst("addi s0, sp, 32");

    /* ============== 代码主体部分 ============== */
    codegen->append_inst(".main_label_entry", ASMInstruction::Label);  // 主代码段标签

    /* 浮点数比较操作 (5.5 > 1.0) */
    codegen->append_inst("%op0 = fcmp ugt float 0x4016000000000000, 0x3ff0000000000000",
                        ASMInstruction::Comment);
    offset_map["%op0"] = -24;  // 比较结果存储在s0-24位置
    
    // 加载单精度浮点数5.5（十六进制表示0x40160000）
    codegen->append_inst("li t0, 0x40160000");
    codegen->append_inst("fmv.w.x ft0, t0");  // 将整数值移动到浮点寄存器ft0
    
    // 加载单精度浮点数1.0（十六进制表示0x3f800000）
    codegen->append_inst("li t1, 0x3f800000");
    codegen->append_inst("fmv.w.x ft1, t1");
    
    // 执行浮点比较（如果ft1 < ft0则设置t2=1）
    codegen->append_inst("flt.s t2, ft1, ft0");
    codegen->append_inst("sw t2, -24(s0)");  // 存储比较结果

    /* 布尔值到整型的零扩展 */
    codegen->append_inst("%op1 = zext i1 %op0 to i32", ASMInstruction::Comment);
    offset_map["%op1"] = -28;  // 转换结果存储在s0-28位置
    codegen->append_inst("lw t0, -24(s0)");
    codegen->append_inst("sw t0, -28(s0)");  // 实际零扩展操作（RISC-V中布尔值已经是32位）

    /* 条件判断（检查%op1是否不等于0） */
    codegen->append_inst("%op2 = icmp ne i32 %op1, 0", ASMInstruction::Comment);
    offset_map["%op2"] = -32;  // 判断结果存储在s0-32位置
    codegen->append_inst("lw t0, -28(s0)");
    codegen->append_inst("snez t1, t0");  // 如果t0 != 0则t1=1
    codegen->append_inst("sw t1, -32(s0)");

    /* 条件分支指令 */
    codegen->append_inst("br i1 %op2, label %label3, label %label4",
                        ASMInstruction::Comment);
    codegen->append_inst("lw t0, -32(s0)");
    codegen->append_inst("bnez t0, .main_label3");  // 如果t0!=0跳转到label3
    codegen->append_inst("j .main_label4");        // 否则跳转到label4

    /* 分支目标1：返回233 */
    codegen->append_inst(".main_label3", ASMInstruction::Label);
    codegen->append_inst("ret i32 233", ASMInstruction::Comment);
    codegen->append_inst("li a0, 233");  // 设置返回值233到a0寄存器
    codegen->append_inst("j main_exit"); // 跳转到公共退出点

    /* 分支目标2：返回0 */
    codegen->append_inst(".main_label4", ASMInstruction::Label);
    codegen->append_inst("ret i32 0", ASMInstruction::Comment);
    codegen->append_inst("li a0, 0");    // 设置返回值0到a0寄存器
    codegen->append_inst("j main_exit"); // 跳转到公共退出点

    /* ============== 收尾部分 (Epilogue) ============== */
    codegen->append_inst("main_exit", ASMInstruction::Label);
    // 恢复返回地址寄存器(ra)
    codegen->append_inst("ld ra, 24(sp)");
    // 恢复旧的帧指针(s0)
    codegen->append_inst("ld s0, 16(sp)");
    // 释放栈空间（32字节）
    codegen->append_inst("addi sp, sp, 32");
    // 函数返回（跳转到ra寄存器指定的地址）
    codegen->append_inst("jr ra");
}
